import httpx
import re
import json
import execjs


class GetEncryptedUrl:

    def __init__(self, url):
        self.url = url
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
        }
        self.client = httpx.Client(http2=True)
        self.data = ""

    def get_data(self):
        response = self.client.get(url=self.url, headers=self.headers)
        self.data = response.text

    def parse_data(self):
        json_str = re.search(r'<script type="text/javascript">var player_aaaa=(.*?)</script>', self.data, re.S).group(1)
        json_dict = json.loads(json_str)
        link = json_dict['url']
        link_next = json_dict['url_next']
        return link, link_next

    def run(self):
        self.get_data()
        return self.parse_data()


class DecryptUrl:

    def __init__(self, url, url_next):
        self.url = url
        self.url_next = url_next
        self.client = httpx.Client(http2=True)
        self.headers = {
            "authority": "player.ddzyku.com:3653",
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
            "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6,ko;q=0.5",
            "cache-control": "no-cache",
            "pragma": "no-cache",
            "sec-ch-ua": "\"Not A(Brand\";v=\"99\", \"Google Chrome\";v=\"121\", \"Chromium\";v=\"121\"",
            "sec-ch-ua-mobile": "?0",
            "sec-ch-ua-platform": "\"Windows\"",
            "sec-fetch-dest": "document",
            "sec-fetch-mode": "navigate",
            "sec-fetch-site": "none",
            "sec-fetch-user": "?1",
            "upgrade-insecure-requests": "1",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
        }
        self.ctx = None
        self.param_data = ""
        self.cipher = ""

    def param_data_encrypt(self):
        with open('request_params_decrypt.js', 'r', encoding='utf-8') as f:
            json_code = f.read()
            self.ctx = execjs.compile(json_code)
            json_dict = {
                "url": self.url,
                "next_url": self.url_next
            }
            # 把空格替换成空，这里要小心。'{"url":"6R...}'   键值对的冒号后面都没有空格
            arg = json.dumps(json_dict).replace(' ', '')
            # 调用JS代码生成加密的请求参数data
            param_data = self.ctx.call("encryptWithAES", arg)
            self.param_data = param_data

    def get_url(self):
        get_urls_api = "https://player.ddzyku.com:3653/getUrls"
        # 这里有个坑，data必须是通过参数传入params中，才可以获得完整响应数据
        response = self.client.get(url=get_urls_api, headers=self.headers, params={"data": self.param_data})
        self.cipher = response.text

    def decrypt_url(self):
        with open('response_data_decrypt.js', 'r', encoding='utf-8') as f:
            self.ctx = execjs.compile(f.read())
            m3u8 = self.ctx.call("decryptWithAES", self.cipher)
            json_dict = json.loads(m3u8)
            m3u8_url = json_dict['data']['url']
            m3u8_next_url = json_dict['data']['next_url']
            print(m3u8_url, m3u8_next_url, sep='\n')

    def run(self):
        # 自己构造请求参数加密的逻辑，并得到加密后的请求参数：data
        self.param_data_encrypt()
        # 带着加密参数去请求服务器得到，加密响应数据，这个加密的数据就是加密的m3u8链接
        self.get_url()
        # 解密m3u8链接
        self.decrypt_url()


if __name__ == '__main__':
    anime_url = "https://555dyy10.com/vodplay/370779-5-3.html"

    # 实例化，并运行爬取加密URL的爬虫
    spider = GetEncryptedUrl(anime_url)
    decrypt_url, decrypt_url_next = spider.run()
    # 实例化，并运行构造解密参数并获得加密m3u8链接的爬虫
    decipher = DecryptUrl(decrypt_url, decrypt_url_next)
    decipher.run()
